﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestXmodem_1K
{
    public class XemodemHelper
    {
        SerialPort sport = new SerialPort();

        public byte[] ReadBytes(string filePaths)
        {
            FileStream fs = new FileStream(filePaths, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            byte[] bys = new byte[1024];//br.ReadBytes(1024);
            for(int i=0;i<1024;i++)
            {
                if (br.ReadByte() == 0)
                {
                    bys[i] = 0x1A;
                }
                else
                {
                    bys[i] = br.ReadByte();
                }
            }
            return bys;
        }

        public void SendBytes(string filePaths)
        {
            byte[] byss = new byte[1024];
            byte[] buff = new byte[1024];
            byss = ReadBytes(filePaths);
            
            SendPacket(byss);
            while (true)
            {
                Task.Delay(1000);
                if (sport.BytesToRead > 0)
                {
                    sport.Read(buff, 0, buff.Length);
                }
                if (buff.Length > 0)
                {
                    string ss = Encoding.Default.GetString(buff);
                    if (ss == "ACK" || ss == "NAK")
                    {

                    }
                  }

            }
            
        }

        public void SendPacket(byte[] bys)
        {
            byte[] data;

            data = new byte[3 + bys.Length + 2];
            data[0] =0x01;
            data[1] = 1;
            data[2] = Convert.ToByte((~data[1]));
            for (int i = 0; i < bys.Length; i++)
            {
                data[3 + i] = bys[i];
            }
            

            byte[] crc = CRC16(bys.ToList());
            data[3 + bys.Length + 1] = crc[0];
            data[3 + bys.Length + 2] = crc[1];



            sport.Write(data, 0, data.Length);
        }

        private byte[] CRC16(List<byte> value, ushort poly = 0xA001, ushort crcInit = 0xFFFF)
        {
            if (value == null || !value.Any())
                throw new ArgumentException("");

            //运算
            ushort crc = crcInit;
            for (int i = 0; i < value.Count; i++)
            {
                crc = (ushort)(crc ^ (value[i]));
                for (int j = 0; j < 8; j++)
                {
                    crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ poly) : (ushort)(crc >> 1);
                }
            }
            byte hi = (byte)((crc & 0xFF00) >> 8);  //高位置
            byte lo = (byte)(crc & 0x00FF);         //低位置

            return new byte[]
            {
                lo,hi
            };
        }
    }
}
